<?php

/**
 * @version         $Id$
 * @create          2013-11-09 21:11:44 By xjiujiu
 * @description     HongJuZi Framework
 * @copyRight       Copyright (c) 2011-2012 http://www.xjiujiu.com.All right reserved
 */

defined('_HEXEC') or die('Restricted access!');
//导入引用文件
HClass::import('vendor.sdk.taobao.sms.SignatureHelper', false);
HClass::import('config.popo.linkeddatapopo, app.public.action.publicaction, model.linkeddatamodel');

/**
 * 用户验证码的动作类 
 * 
 * 主要处理主页的相关请求动作 
 * 
 * @author          xjiujiu <xjiujiu@foxmail.com>
 * @package         app.public.action
 * @since           1.0.0
 */
class SmsAction extends PublicAction
{

    /**
     * 构造函数 
     * 
     * 初始化类里的变量 
     * 
     * @access public
     */
    public function __construct() 
    {
        $this->_popo    = new LinkeddataPopo();
        $this->_model   = new LinkeddataModel($this->_popo);
        $this->_model->setRelItemModel('user', 'code');
    }

    /**
     * 发送更换手机号验证码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function aupdatesend()
    {
        HVerify::isAjax();
        $phone      = HRequest::getParameter('phone');
        $this->_checkPhoneUsed($phone);
        $this->_doSend($phone, 'SMS_7500146');
    }

    /**
     * 检测手机号是否被使用过
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access private
     * @param $phone 手机号
     * @throws HVerifyException 异常
     */
    private function _checkPhoneUsed($phone, $isSelf = false)
    {
        $user   = HClass::quickLoadModel('user');
        $where  = '`phone` = \'' . $phone . '\'';
        if($isSelf) {
            $isSelf     .= '  AND `id` != ' . intval(HSession::getAttribute('id', 'user'));
        }
        if($user->getRecordByWhere($where)) {
            throw new HVerifyException('手机号码已经被他人使用，请直接登录或找回密码？');
        }   
    }

    /**
     * 发送验证码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function asendforregister()
    {
        $phone = HRequest::getParameter('phone');
        if( !preg_match("/^1[34578]{1}\d{9}$/", $phone)) {
            throw new HApiException('手机号格式不正确');
        }
        $this->_checkAccessTokenCode();
        $res    = $this->_doSend($phone, 'SMS_140685138');
    }

    private function _checkAccessTokenCode()
    {
        $code = HRequest::getParameter('code');
        if( !$code ) {
            throw new HApiException('请输入图片验证码');
        }

        $linkeddata  = HClass::quickLoadModel('linkeddata');
        $linkeddata->setRelItemModel('user', 'accesstoken');
        $accessToken = $linkeddata->getRecordByWhere('`item_id` = \'' . HRequest::getParameter('access_token') . '\'');
        $userId      = $accessToken['rel_id'];

        $linkeddata = HClass::quickLoadModel('linkeddata');
        $linkeddata->setRelItemModel('user', 'code');
        $info       = $linkeddata->getRecordByWhere('`rel_id` = ' . $userId . ' AND `item_id` = \'' . $code . '\'');

        if( !$info ) {
            throw new HApiException('验证码不正确，请重新输入');
        }

        $linkeddata->deleteByWhere('`rel_id` = ' . $userId);
    }
    /**
     * 发送换手机号码验证码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function asendforresetphone()
    {
        $phone      = HVerify::isPhone(HRequest::getParameter('phone'));
        if($phone == HSession::getAttribute('phone', 'user')) {
            throw new HVerifyException('您已绑定此手机号，请确认哦～');
        }
        $this->_asendwithvcode('SMS_7500143');
    }

    /**
     * 发送找回密码码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function asendforforgotpwd()
    {
        $this->_asendwithvcode('SMS_7500144');
    }

    /**
     * 发送找登陆码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function alogincode()
    {
        $this->_asendwithvcode('SMS_7500148');
    }

    /**
     * 发送验证码同时需要图片验证码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access protected
     */
    protected function _asendwithvcode($tplCode)
    {
        HVerify::isAjax();
        $phone  = HVerify::isPhone(HRequest::getParameter('phone'), '手机号码');
        $vcode  = HRequest::getParameter('vcode');
        if( strtolower($vcode) != strtolower( HSession::getAttribute('vcode'))) {
            throw new HVerifyException('验证码不正确');
        }
        $this->_doSend($phone, $tplCode);
    }

    public function asendwithvcode()
    {
        $tplCode = HObject::GC('SMS')['tpl_code'];
        $this->_asendwithvcode($tplCode);
    }

    /**
     * 发送绑定验证码
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access public
     */
    public function abind()
    {
        HVerify::isAjax();
        $phone  = HVerify::isPhone(HRequest::getParameter('phone'));
        $user   = HClass::quickLoadModel('user');
        $record = $user->getRecordByWhere('`phone` = \'' . $phone . '\'');
        if($record && $record['id'] != HSession::getAttribute('id', 'user')) {
            throw new HVerifyException('手机已经被他人用过，请更换一个吧～');
        }
        $this->_doSend($phone, 'SMS_7500150');
    }

    /**
     * 执行发送任务
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access private
     * @param $phone 手机号
     */
    private function _doSend($phone, $tplCode)
    {
        $phone  = strtr($phone, array('+' => '', ' ' => ''));
        $data   = array(
            'item_id' => rand(1000, 9999),
            'rel_id' => $phone,
            'extend' => 1,
            'create_time' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']),
            'author' => 0
        );
        $where      = '`rel_id` = \'' . $data['rel_id'] . '\' AND `extend` > 4';
        $record     = $this->_model->getRecordByWhere($where);
        if($record && (60 > $_SERVER['REQUEST_TIME'] - strtotime($record['create_time']))) {
            throw new HApiException('您操作太快了，1分钟内只能发送一次！');
        }
        $record ? $this->_model->delete($record['id']) : '';
        $id         = $this->_model->add($data);
        if(1 > $id) {
            throw new HApiException('添加验证码到数据库失败！');
        }
        $data['id']     = $id;
        $rs             = $this->_sendSMSByAliyun($data, $tplCode);
        $this->_updateCodeInfoByAliyun($rs, $id);

        HResponse::json(array('rs' => true));
    }

    private function _updateCodeInfoByOther($rs, $id)
    {
        $json               = json_encode($rs, JSON_UNESCAPED_UNICODE);
        $data['comment']    = $json;
        if($rs['status']) {
            $data['extend'] = 4;
            $this->_model->editByWhere($data, '`id` = ' . $id);
            throw new HVerifyException('短信发送正在维护中，请稍后再试！');
        }
        $data['extend']     = 2;
        $this->_model->editByWhere($data, '`id` = ' . $id);
    }

    private function _updateCodeInfoByAliyun($rs, $id)
    {
        $json   = json_encode($rs, JSON_UNESCAPED_UNICODE);
        $data['extend']    = $json;
        if('OK' != $rs->Code) {
            $data['extend']     = -1;
            $this->_model->editByWhere($data, '`id` = ' . $id);
            if($rs->Code == 'isv.BUSINESS_LIMIT_CONTROL') {
                throw new HApiException('您操作太快了，1分钟内只能发送一次！');
            }
            throw new HApiException('短信发送正在维护中，请稍后再试！');
        } 
        $data['extend']     = 2;
        $this->_model->editByWhere($data, '`id` = ' . $id);
    }

    /**
     * 发送短信
     * 
     * @author xjiujiu <xjiujiu@foxmail.com>
     * @access private
     * @param $data 发送内容
     * @return 发送结果
     */
    private function _sendSMSByAliyun($data, $tplCode)
    {
        $params         = array ();
        $smsCfg         = HObject::GC('SMS');
        // *** 需用户填写部分 ***
        // fixme 必填: 请参阅 https://ak-console.aliyun.com/ 取得您的AK信息
        $accessKeyId        = $smsCfg['appid'];
        $accessKeySecret    = $smsCfg['secret'];
        // fixme 必填: 短信接收号码
        $params["PhoneNumbers"] = strtr($data['rel_id'], array('+' => '', ' ' => ''));
        // fixme 必填: 短信签名，应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
        $params["SignName"] = $smsCfg['sign_name'];
        // fixme 必填: 短信模板Code，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
        $params["TemplateCode"] = $tplCode;
        // fixme 可选: 设置模板参数, 假如模板中存在变量需要替换则为必填项
        $params['TemplateParam'] = Array (
            "code" => $data['item_id'],
            "product" => $smsCfg['product']
        );
        // fixme 可选: 设置发送短信流水号
        $params['OutId'] = $data['id'];
        // fixme 可选: 上行短信扩展码, 扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段
        $params['SmsUpExtendCode'] = '';
        // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
        if(!empty($params["TemplateParam"]) && is_array($params["TemplateParam"])) {
            $params["TemplateParam"] = json_encode($params["TemplateParam"], JSON_UNESCAPED_UNICODE);
        }
        // 初始化SignatureHelper实例用于设置参数，签名以及发送请求
        $helper = new SignatureHelper();
        // 此处可能会抛出异常，注意catch
        $content = $helper->request(
            $accessKeyId,
            $accessKeySecret,
            "dysmsapi.aliyuncs.com",
            array_merge($params, array(
                "RegionId" => "cn-hangzhou",
                "Action" => "SendSms",
                "Version" => "2017-05-25",
            ))
            // fixme 选填: 启用https
            // ,true
        );
        return $content;
    }

}

?>
